package icu.zqyhdm.blog.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import icu.zqyhdm.blog.mapper.ArticleMapper;
import icu.zqyhdm.blog.mapper.ArticleTagMapper;
import icu.zqyhdm.blog.mapper.UserMapper;
import icu.zqyhdm.blog.service.ArticleService;
import icu.zqyhdm.blog.vo.TagVo;
import icu.zqyhdm.exception.MyException;
import icu.zqyhdm.result.ResultCodeEnum;
import icu.zqyhdm.blog.entity.ArticleTag;
import icu.zqyhdm.blog.entity.Tag;
import icu.zqyhdm.blog.mapper.TagMapper;
import icu.zqyhdm.blog.service.TagService;
import icu.zqyhdm.helper.JwtHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description
 * @Author lifu
 * @Date 2021/6/22 21:18
 */
@Service
public class TagServiceImpl extends ServiceImpl<TagMapper, Tag> implements TagService {
    @Autowired
    private ArticleTagMapper articleTagMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private ArticleService articleService;

    //查询所有文章标签，标签名去重，并根据标签对应的文章数量降序排
    @Override
    @Cacheable(value = "blog:tagList",keyGenerator = "keyGenerator")
    public List<TagVo> getAllTag() {
        List<Tag> tagList = baseMapper.selectList(Wrappers.emptyWrapper());
        List<TagVo> tagVoList = BeanUtil.copyToList(tagList, TagVo.class);

        Map<String,TagVo> map = new HashMap<>(tagVoList.size()); // 用来存放文章标签的名
        for(TagVo tagVo : tagVoList){
            //把文章数量信息封装进文章标签
            setTagVoInfo(tagVo);
            //标签名去重
            if(map.containsKey(tagVo.getTagName())){
                Integer rawCount = map.get(tagVo.getTagName()).getArticleNum();
                Integer newCount = tagVo.getArticleNum() + rawCount;
                //把新的数量存进tagVo
                map.get(tagVo.getTagName()).setArticleNum(newCount);
            }else {
                map.put(tagVo.getTagName(),tagVo);
            }
        }
        tagVoList = new ArrayList<>(map.values());
        Collections.sort(tagVoList, new Comparator<TagVo>() {
            @Override
            public int compare(TagVo o1, TagVo o2) {
                //按照value值，从大到小排序
                return o2.getArticleNum() - o1.getArticleNum();
            }
        });
        return tagVoList;
    }

    //查询某个用户的文章标签，并根据标签对应的文章数量降序排
    @Override
    @Cacheable(value = "blog:tagList",keyGenerator = "keyGenerator")
    public List<TagVo> getTagByUserId(Integer userId) {
        QueryWrapper<Tag> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("author_id",userId);
        List<Tag> tagList = baseMapper.selectList(queryWrapper);
        if(tagList.isEmpty()){
            return new ArrayList<TagVo>();
        }
        List<TagVo> tagVoList = BeanUtil.copyToList(tagList, TagVo.class);
        for(TagVo tagVo : tagVoList){
            //把文章数量信息封装进文章标签
            setTagVoInfo(tagVo);
        }
        Collections.sort(tagVoList, new Comparator<TagVo>() {
            @Override
            public int compare(TagVo o1, TagVo o2) {
                //按照value值，从大到小排序
                return o2.getArticleNum() - o1.getArticleNum();
            }
        });
        return tagVoList;
    }

    //增加
    @Override
    @CacheEvict(value = "blog:tagList",allEntries = true)
    public void saveTag(String token, String tagName) {
        Integer userId = JwtHelper.getUserId(token);
        //判断文章标签是否已存在
        QueryWrapper<Tag> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("tag_name",tagName).eq("author_id",userId);
        int count = baseMapper.selectCount(queryWrapper);
        if(count > 0){
            throw new MyException(ResultCodeEnum.TAG_EXIST_ERROR);
        }
        Tag tag = new Tag();
        tag.setTagName(tagName);
        tag.setAuthorId(userId);
        int i = baseMapper.insert(tag);
        if(i < 1){
            throw new MyException(ResultCodeEnum.NET_ERROR);
        }
    }

    //修改
    @Override
    @CacheEvict(value = "blog:tagList",allEntries = true)
    public void updateTag(String token, Tag tag) {
        Integer userId = JwtHelper.getUserId(token);
        Integer authorId = tag.getAuthorId();

        //用户的权限判断，非作者本人不能修改
        Integer role = userMapper.selectById(userId).getRole();
        if(!(authorId.equals(userId) || role.intValue() == 1)){
            throw new MyException(ResultCodeEnum.AUTHORITY_ERROR);
        }
        //判断文章标签是否已存在
        String tagName = tag.getTagName();
        QueryWrapper<Tag> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("tag_name",tagName).eq("author_id",userId);
        int count = baseMapper.selectCount(queryWrapper);
        if(count > 0){
            throw new MyException(ResultCodeEnum.TAG_EXIST_ERROR);
        }
        int i = baseMapper.updateById(tag);
        if(i < 1){
            throw new MyException(ResultCodeEnum.NET_ERROR);
        }
    }

    //删除
    @Override
    @CacheEvict(value = "blog:tagList",allEntries = true)
    @Transactional(rollbackFor=Exception.class)
    public void deleteTag(String token, Integer tagId) {
        //用户的权限判断，非管理员和作者本人不能修改
        Integer userId = JwtHelper.getUserId(token);
        Integer authorId = baseMapper.selectById(tagId).getAuthorId();
        Integer role = userMapper.selectById(userId).getRole();
        if(!(authorId.equals(userId) || role.intValue() == 1)){
            throw new MyException(ResultCodeEnum.AUTHORITY_ERROR);
        }
        //事务
        try {
            //先删除标签表
            baseMapper.deleteById(tagId);
            //标签对应的文章id列表
            List<ArticleTag> articleTagList = articleTagMapper.selectList(new QueryWrapper<ArticleTag>().eq("tag_id",tagId));
            List<Integer> articleIdList = articleTagList.stream().map(articleTag -> {
                return articleTag.getArticleId();
            }).collect(Collectors.toList());
            // 删除文章
            for(Integer articleId : articleIdList){
                articleService.deleteArticle(token,articleId);// 顺带会删除userInfo的缓存
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new MyException(ResultCodeEnum.NET_ERROR);
        }
    }
    //查询
    @Override
    public TagVo getTagById(Integer tagId) {
        Tag tag = baseMapper.selectById(tagId);
        TagVo tagVo = BeanUtil.copyProperties(tag, TagVo.class);
        //封装信息
        return setTagVoInfo(tagVo);
    }

    //把文章数量信息封装进文章标签
    private TagVo setTagVoInfo(TagVo tagVo){
        QueryWrapper<ArticleTag> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("tag_id",tagVo.getId());
        Integer count = articleTagMapper.selectCount(queryWrapper);
        tagVo.setArticleNum(count);
        return tagVo;
    }

}
